/*
 * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd
 * www.monkeyk.com
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * MONKEYK Information Technology Co. Ltd ("Confidential Information").
 * You shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement you
 * entered into with MONKEYK Information Technology Co. Ltd.
 */
package com.monkeyk.os.infrastructure.shiro;

import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

import com.monkeyk.os.domain.users.UserApi;
import com.monkeyk.os.domain.users.UsersRepository;
import com.monkeyk.os.util.BlankUtils;

/**
 * 2015/10/27
 * <p/>
 * Support Redis
 *
 * @author Shengzhao Li
 */
public class AuthzRealm extends AuthorizingRealm implements InitializingBean {


    private static final Logger LOG = LoggerFactory.getLogger(AuthzRealm.class);


    protected UsersRepository usersRepository;

    public AuthzRealm() {
        super();
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        String username = getUsername(token);
        String password= getPassword(token);

        // Null username is invalid
        if (BlankUtils.isBlank(username)) {
            throw new AccountException("Null username are not allowed by this realm.");
        }
        // Null password is invalid
        if (BlankUtils.isBlank(password)) {
        	throw new AccountException("Null password are not allowed by this realm.");
        }
        UserApi users  = usersRepository.findUserByUsername(username);
        LOG.debug("Load Users[{}] by username: {}", users, username);

        SimpleAuthenticationInfo info = null;
        if (BlankUtils.isNotBlank(users)) {
            info = new SimpleAuthenticationInfo(username, users.getPassword().toCharArray(), getName());
        }

        return info;
    }
    
    //字节转字符串
    protected String charArrayToStr(char[] charArray) {
        if (charArray == null) {
            return null;
        }
        String str = new String(charArray);
        return str;
    }
    //获取用户名
    protected String getUsername(AuthenticationToken token) {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        return upToken.getUsername();
    }
    //获取密码
    protected String getPassword(AuthenticationToken token) {
    	UsernamePasswordToken upToken = (UsernamePasswordToken) token;
    	return charArrayToStr(upToken.getPassword());
    }


    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        return info;
    }

    protected String getUsername(PrincipalCollection principals) {
        //null usernames are invalid
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }

        return (String) getAvailablePrincipal(principals);
    }


    public void setUsersRepository(UsersRepository usersRepository) {
        this.usersRepository = usersRepository;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(usersRepository, "usersRepository is null");
    }
}
